package org.richin.collection.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ListHashMap<K, V> implements ListMap<K, V> {
	/**
	 * 
	 */
	private static final long serialVersionUID = 684212699595130278L;
	private List<K> mKeyList;
	private List<V> mValueList;
	private Map<K, V> mMap;

	public ListHashMap() {

		mKeyList = new ArrayList<K>();
		mValueList = new ArrayList<V>();
		mMap = new HashMap<K, V>();
	}

	public ListHashMap(int initialCapacity, float loadFactor) {

		mKeyList = new ArrayList<K>(initialCapacity);
		mValueList = new ArrayList<V>(initialCapacity);
		mMap = new HashMap<K, V>(initialCapacity, loadFactor);
	}

	public V get(int index) {
		return mValueList.get(index);

	}

	public List<K> getKeyList() {
		return Collections.unmodifiableList(mKeyList);

	}

	public List<V> getValueList() {
		return Collections.unmodifiableList(mValueList);

	}

	public V put(int index, K key, V value) {
		if (!mMap.containsKey(key)) {
			mKeyList.add(index, key);
			mValueList.add(index, value);
			mMap.put(key, value);

			return null;
		}

		mKeyList.remove(index);
		mKeyList.add(index, key);
		mValueList.remove(index);
		mValueList.add(index, value);

		return mMap.put(key, value);

	}

	public V remove(int index) {
		K k = mKeyList.remove(index);

		if (k != null) {
			mValueList.remove(index);

			return mMap.remove(k);
		}

		return null;

	}

	public void clear() {
		mMap.clear();
		mKeyList.clear();
		mValueList.clear();

	}

	public boolean containsKey(Object key) {
		return mMap.containsKey(key);

	}

	public boolean containsValue(Object value) {
		return mMap.containsValue(value);

	}

	public Set<java.util.Map.Entry<K, V>> entrySet() {
		return Collections.unmodifiableSet(mMap.entrySet());

	}

	public V get(Object key) {
		return mMap.get(key);

	}

	public boolean isEmpty() {
		return mMap.isEmpty();

	}

	public Set<K> keySet() {
		return Collections.unmodifiableSet(mMap.keySet());

	}

	public V put(K key, V value) {
		if (!mMap.containsKey(key)) {
			mKeyList.add(key);
			mValueList.add(value);
			mMap.put(key, value);

			return null;
		}

		int index = mKeyList.indexOf(key);

		mKeyList.remove(index);
		mKeyList.add(index, key);
		mValueList.remove(index);
		mValueList.add(index, value);

		return mMap.put(key, value);

	}

	public void putAll(Map<? extends K, ? extends V> m) {
		for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
			put(e.getKey(), e.getValue());
		}

	}

	public V remove(Object key) {
		V v = mMap.remove(key);

		if (v != null) {
			int index = mKeyList.indexOf(key);

			mKeyList.remove(index);
			mValueList.remove(index);
		}

		return v;

	}

	public int size() {
		return mMap.size();

	}

	public Collection<V> values() {
		return Collections.unmodifiableCollection(mMap.values());

	}

	public ListMap<K, V> add(K key, V value) {
		put(key, value);
		return this;
	}

}
